home *** CD-ROM | disk | FTP | other *** search
Text File | 2010-02-04 | 35.1 KB | 1,242 lines |
- /*------------------------------------------------------------------------------
- Copyright (c) 2008 Ensolis, LLC. All Rights Reserved.
- ----------------------------------------------------------------------------*/
-
- /******************************************************************************
- * DTD and Namespace Constants for icons.xml
- *****************************************************************************/
- const ICONS_DTD = "http://forecastfox.ensolis.com/specs/1.0/icons.dtd";
- const ICONS_NS = "http://forecastfox.ensolis.com/specs/1.0/icons";
-
- /******************************************************************************
- * Icon Pack Constants
- *****************************************************************************/
- const PACK_ROOT = "http://www.ensolis.com/2005/icon-pack/install";
- const PACK_PREFIX = "http://www.ensolis.com/2005/icon-manager#";
- const PACK_PROPERTIES = ["id", "name", "version", "website", "author",
- "target", "smallWidth", "smallHeight", "largeWidth",
- "largeHeight"];
- const PACK_FILES = ["pack.rdf", "small/01.png", "small/02.png", "small/03.png",
- "small/04.png", "small/05.png", "small/06.png",
- "small/07.png", "small/08.png", "small/11.png",
- "small/12.png", "small/13.png", "small/14.png",
- "small/15.png", "small/16.png", "small/17.png",
- "small/18.png", "small/19.png", "small/20.png",
- "small/21.png", "small/22.png", "small/23.png",
- "small/24.png", "small/25.png", "small/26.png",
- "small/29.png", "small/30.png", "small/31.png",
- "small/32.png", "small/33.png", "small/34.png",
- "small/35.png", "small/36.png", "small/37.png",
- "small/38.png", "small/39.png", "small/40.png",
- "small/41.png", "small/42.png", "small/43.png",
- "small/44.png", "small/radar.png", "small/swa.png",
- "large/01.png", "large/02.png", "large/03.png",
- "large/04.png", "large/05.png", "large/06.png",
- "large/07.png", "large/08.png", "large/11.png",
- "large/12.png", "large/13.png", "large/14.png",
- "large/15.png", "large/16.png", "large/17.png",
- "large/18.png", "large/19.png", "large/20.png",
- "large/21.png", "large/22.png", "large/23.png",
- "large/24.png", "large/25.png", "large/26.png",
- "large/29.png", "large/30.png", "large/31.png",
- "large/32.png", "large/33.png", "large/34.png",
- "large/35.png", "large/36.png", "large/37.png",
- "large/38.png", "large/39.png", "large/40.png",
- "large/41.png", "large/42.png", "large/43.png",
- "large/44.png", "large/swa.png"];
-
- /******************************************************************************
- * Reads an icon pack file from disk validates the pack has the required
- * files and properties and creates a icon pack item. If the pack file is not
- * valid then a error item is created.
- * This implements the nsIRunnable interface so it could
- * be dispatched to a thread.
- *
- * @param File to read.
- * @return An ffIPackItem if the file is valid, otherwise a ffIErrorItem is
- * returned. Callers should check the instanceof to determine.
- *****************************************************************************/
- function PackReader(aFile)
- {
- this.file = aFile;
- }
- PackReader.prototype = {
- _file: null,
- _item: null,
- _dskSvc: null,
- _rdfSvc: null,
- _temp: null,
- _bundle: null,
-
- get file() { return this._file; },
- set file(aVal) { this._file = aVal; },
-
- get item() { return this._item; },
- set item(aVal) { this._item = aVal; },
-
- get bundle() { return this._bundle; },
-
- ///////////////////////////
- // nsISupports
- QueryInterface: function PackReader_QueryInterface(aIID)
- {
- if (!aIID.equals(Ci.nsIRunnable) &&
- !aIID.equals(Ci.nsISupports))
- throw Components.results.NS_ERROR_NO_INTERFACE;
- return this;
- },
-
- ///////////////////////////
- // nsIRunnable
- run: function PackReader_run()
- {
- //initialize the needed variables
- this._init();
-
- //open the zip file
- var reader = Cc["@mozilla.org/libjar/zip-reader;1"].
- createInstance(Ci.nsIZipReader);
- try {
- //toolkit 2.0 and prior or non toolkit
- if ("init" in reader) {
- reader.init(this.file);
- reader.open();
-
- //toolkit 3.0
- } else
- reader.open(this.file);
-
- //error opening the zip file
- } catch(e) {
- this._setError("open", this.file.path);
- this._destroy(reader);
- return;
- }
-
- //get the zip entries
- var entries = this._getEntries(reader);
-
- //check the entries are valid
- if (!this._checkEntries(entries)) {
- this._destroy(reader);
- return;
- }
-
- //get the install manifest
- var manifest = this._getManifest(reader);
-
- //check the manifest is valid
- if (!this._checkManifest(manifest)) {
- this._destroy(reader);
- return;
- }
-
- //create the pack item
- this._item = this._createItem(manifest);
-
- //cleanup and return
- this._destroy(reader);
- return;
- },
-
- /**
- * Initialize internal variables.
- */
- _init: function PackReader__init()
- {
- //get the stringbundle
- this._bundle = getBundle();
-
- //get the disk service
- var mgrSvc = Cc["@ensolis.com/forecastfox/manager-service;1"].
- getService(Ci.ffIManagerService);
- this._dskSvc = mgrSvc.disk;
-
- //get the rdf service
- this._rdfSvc = Cc["@mozilla.org/rdf/rdf-service;1"].
- getService(Ci.nsIRDFService);
-
- //get a temp file for the install manifest
- this._temp = this._dskSvc.get("icon-pack.rdf", TYPE_TEMP);
- },
-
- /**
- * cleanup internal variables and close the zip reader.
- *
- * @param The zip reader.
- */
- _destroy: function PackReader__destroy(aReader)
- {
- //close the reader
- try {
- aReader.close();
- } catch(e) {}
-
- //remove the temp file
- try {
- removeFile(this._temp);
- } catch(e) {}
-
- //clear variables
- this._dskSvc = null;
- this._rdfSvc = null;
- this._temp = null;
- this._bundle = null;
- },
-
- _setError: function PackReader__setError(aType, aData)
- {
- //get the error name and message
- const PREFIX = "ff.packs.read.";
- var name = this.bundle.GetStringFromName(PREFIX + "name");
- var message = this.bundle.formatStringFromName(PREFIX + aType + ".message",
- [aData], 1);
-
- //create an error item
- this._item = Cc["@ensolis.com/forecastfox/error-item;1"].
- createInstance(Ci.ffIErrorItem);
-
- //set the error
- this._item.init(SEVERITY_ERROR, name, message);
- },
-
- /**
- * Get the entries in the zip file.
- *
- * @param The zip reader.
- * @return An object containing the entries.
- */
- _getEntries: function PackReader__getEntries(aReader)
- {
- var rv = {};
-
- //loop through the entries
- var entries = aReader.findEntries("*");
- var entry = null;
-
- //toolkit 2.0 and prior or non toolkit
- if ("hasMoreElements" in entries) {
- while (entries.hasMoreElements()) {
- entry = entries.getNext().QueryInterface(Ci.nsIZipEntry);
- rv[entry.name] = entry.name;
- }
-
- //toolkit 3.0
- } else {
- while (entries.hasMore()) {
- entry = entries.getNext();
- rv[entry] = entry;
- }
- }
-
- //return the object
- return rv;
- },
-
- /**
- * Check that all the required entries exist.
- *
- * @param An object containing the entries.
- * @return False if an entry is missing.
- */
- _checkEntries: function PackReader__checkEntries(aEntries)
- {
- //loop through required files
- for (var i=0; i<PACK_FILES.length; i++) {
- var file = PACK_FILES[i];
-
- //missing an entry
- if (!aEntries.hasOwnProperty(file)) {
- this._setError("entry", file);
- return false;
- }
- }
-
- //all entries exist
- return true;
- },
-
- /**
- * Extract the manifest file to a temp file and
- * load it into an RDF datasource.
- *
- * @param The zip reader.
- * @return The manifest file.
- */
- _getManifest: function PackReader__getManifest(aReader)
- {
- //extract the file
- aReader.extract("pack.rdf", this._temp);
-
- //load the datasource
- var URL = this._dskSvc.getFileURL(this._temp);
- return this._rdfSvc.GetDataSourceBlocking(URL);
- },
-
- /**
- * Check that all the required properties exist in the manifest.
- *
- * @param The manifest datasource.
- * @return False if a property is missing.
- */
- _checkManifest: function PackReader__checkManifest(aManifest)
- {
- //get the root resource
- var root = this._rdfSvc.GetResource(PACK_ROOT);
-
- //check for the required properties
- for (var i=0; i<PACK_PROPERTIES.length; i++) {
- var property = PACK_PROPERTIES[i];
-
- //get the property resource
- var resource = this._rdfSvc.GetResource(PACK_PREFIX + property);
-
- //resource is missing
- if (!aManifest.hasArcOut(root, resource)) {
- this._setError("manifest", property);
- this._rdfSvc.UnregisterDataSource(aManifest);
- return false;
- }
- }
-
- //all properties exist
- return true;
- },
-
- /**
- * Create an icon pack from the pack manifest.
- *
- * @param The manifest datasource.
- * @return An ffIPackItem object.
- */
- _createItem: function PackReader__createItem(aManifest)
- {
- //create an empty pack item
- var pack = Cc["@ensolis.com/forecastfox/pack-item;1"].
- createInstance(Ci.ffIPackItem);
-
- //get the root resource
- var root = this._rdfSvc.GetResource(PACK_ROOT);
-
- //copy the required properties.
- for (var i=0; i<PACK_PROPERTIES.length; ++i) {
- var property = PACK_PROPERTIES[i];
-
- //get the property resource
- var resource = this._rdfSvc.GetResource(PACK_PREFIX + property);
-
- //set the pack property
- var value = this._evalResource(aManifest, root, resource);
- if (property == "id")
- pack.setProperty("ID", value);
- else
- pack.setProperty(property, value);
- }
-
- //loop through exemptions
- resource = this._rdfSvc.GetResource(PACK_PREFIX + "exemption");
- var targets = aManifest.GetTargets(root, resource, true);
- while (targets.hasMoreElements()) {
- var target = targets.getNext().QueryInterface(Ci.nsIRDFResource);
-
- //create an empty icon item
- var icon = Cc["@ensolis.com/forecastfox/icon-item;1"].
- createInstance(Ci.ffIIconItem);
-
- //get the exemption resources
- var index = this._rdfSvc.GetResource(PACK_PREFIX + "index");
- var size = this._rdfSvc.GetResource(PACK_PREFIX + "size");
- var width = this._rdfSvc.GetResource(PACK_PREFIX + "width");
- var height = this._rdfSvc.GetResource(PACK_PREFIX + "height");
-
- //set the values
- icon.setProperty("index", this._evalResource(aManifest, target, index));
- icon.setProperty("size", this._evalResource(aManifest, target, size));
- icon.setProperty("width", this._evalResource(aManifest, target, width));
- icon.setProperty("height", this._evalResource(aManifest, target, height));
- icon.setProperty("isExemption", true);
-
- //add the icon to the pack
- pack.setItem(icon);
- }
-
- //unregister the datasource
- this._rdfSvc.UnregisterDataSource(aManifest);
-
- //return the pack item
- return pack;
- },
-
- /**
- * Evaluate an RDF resource and return its value.
- *
- * @param The manifest datasource.
- * @param The root resource.
- * @param The target resource.
- * @return The value of the target.
- */
- _evalResource: function PackReader__evalResource(aManifest, aRoot, aResource)
- {
- //get the target resource
- var target = aManifest.GetTarget(aRoot, aResource, true);
-
- //return the targets value
- if (target instanceof Ci.nsIRDFLiteral)
- return target.Value;
- if (target instanceof Ci.nsIRDFResource)
- return target.Value;
- if (target instanceof Ci.nsIRDFInt)
- return target.Value;
-
- return "undefined";
- }
- };
-
-
- /******************************************************************************
- * Interface for describing the icon pack service. This service should
- * be used for all profile data related changes.
- *
- * @status FROZEN
- * @version 1.0
- ******************************************************************************/
- function PackService()
- {
- //setup additional interfaces
- this._ifaces.push(Ci.nsIObserver);
- this._ifaces.push(Ci.nsISupportsWeakReference);
-
- //setup a new error
- this._error = Cc["@ensolis.com/forecastfox/error-item;1"].
- createInstance(Ci.ffIErrorItem);
- }
- PackService.prototype = {
- __proto__: new ServiceBase("PackService"),
- _dskSvc: null,
- _obSvc: null,
- _items: null,
- _isBatch: null,
- _isLoading: null,
- _flushPending: null,
-
- ///////////////////////////
- // nsIObserver
- observe: function PackService_observe(aSubject, aTopic, aData)
- {
- switch (aTopic) {
-
- //preference change
- case "nsPref:changed":
-
- //ignore changes if we are loading
- if (this.isLoading)
- return;
-
- //current changed
- this.current = this.getItem(getPref(aData));
- break;
- }
- },
-
- ////////////////////////////////
- // ffIService
-
- /**
- * Initialize the component. Called by the manager service. Returns false
- * if the datasource could not be loaded. Chech the lastError property for
- * more information.
- */
- start: function PackService_start()
- {
- //setup the variables
- this._items = {};
- this._isBatch = false;
- this._isLoading = false;
- this._flushPending = false;
-
- //get the disk service
- var mgrSvc = Cc["@ensolis.com/forecastfox/manager-service;1"].
- getService(Ci.ffIManagerService);
- this._dskSvc = mgrSvc.disk;
-
- //get the observer service
- this._obSvc = Cc["@mozilla.org/observer-service;1"].
- getService(Ci.nsIObserverService);
-
- //start batch mode
- this.startBatch();
-
- //remove old files
- this._removeFiles(null);
-
- //load icon packs
- var success = this._loadPacks();
-
- //end batch mode
- this.endBatch();
-
- //setup a preference observer
- var pb2 = this.branch.QueryInterface(Ci.nsIPrefBranchInternal);
- pb2.addObserver("icons.current", this, true);
-
- //return our success code
- return success;
- },
-
- /**
- * Destroy the component. Called by the manager service. This may be
- * called prior to start so it needs to be safe.
- */
- stop: function PackService_stop()
- {
- //remove the pref observer
- var pb2 = this.branch.QueryInterface(Ci.nsIPrefBranchInternal);
- pb2.removeObserver("icons.current", this);
-
- //clear variables
- this._dskSvc = null;
- this._obSvc = null;
- this._items = null;
- this._isBatch = null;
- this._isLoading = null;
- this._flushPending = null;
- },
-
- ////////////////////////////////
- // ffIPackService
-
- /**
- * Currently selected pack item.
- */
- get current() { return this._ensureItem(); },
-
- set current(aVal) {
- //do nothing if null passed in
- if (!aVal)
- return;
-
- //do nothing if we don't have it
- if (!this.hasItem(aVal.ID))
- return;
-
- //load the items properties
- this._items[aVal.ID] = aVal.clone();
- this._loadItem(aVal);
-
- //notify observers
- this._obSvc.notifyObservers(aVal, "forecastfox-icons", "current");
- },
-
- /**
- * Pack service is in batch mode.
- */
- get isBatch() { return this._isBatch; },
-
- /**
- * Icon pack is being loaded into preferences.
- */
- get isLoading() { return this._isLoading; },
-
- /**
- * Pack service has a specific item.
- *
- * @param ID of the pack item.
- * @return True if item exists.
- */
- hasItem: function PackService_hasItem(aID)
- {
- return this._items.hasOwnProperty(aID);
- },
-
- /**
- * Retrieve a pack item returns null if item doesn't exist.
- *
- * @param ID of the pack item.
- * @return A ffIPackItem.
- */
- getItem: function PackService_getItem(aID)
- {
- if (!this.hasItem(aID))
- return null;
- else
- return this._items[aID];
- },
-
- /**
- * Retrieve an array of pack items.
- *
- * @param Count of items in the array.
- * @return An array of ffIPackItem components.
- */
- getItems: function PackService_getItems(aCount)
- {
- //loop through items
- var items = [];
- for (var id in this._items)
- items.push(this._items[id]);
-
- //sort the array
- items.sort(sortByName);
-
- //return the array
- aCount.value = items.length;
- return items;
- },
-
- /**
- * Sets a pack item. Returns false if pack could not be set.
- * Use the lastError property for more information.
- *
- * @param The icon pack file.
- * @return False if pack could not be set.
- */
- setItem: function PackService_setItem(aFile)
- {
- //setup error variables
- const PREFIX = "ff.packs.set.";
- var name = this.bundle.GetStringFromName(PREFIX + "name");
- var message = "";
-
- //error if the file does not exists
- if (!aFile.exists()) {
- message = this.bundle.GetStringFromName(PREFIX + "exist.message");
- this._error.init(SEVERITY_ERROR, name, message);
- return false;
- }
-
- //error if the file is not readable
- if (!aFile.isReadable()) {
- message = this.bundle.formatStringFromName(PREFIX + "read.message",
- [aFile.path], 1);
- this._error.init(SEVERITY_ERROR, name, message);
- return false;
- }
-
- //error if the file is not a jar
- if (!aFile.leafName.match(".jar")) {
- message = this.bundle.GetStringFromName(PREFIX + "jar.message");
- this._error.init(SEVERITY_ERROR, name, message);
- return false;
- }
-
- //read the pack
- var reader = new PackReader(aFile);
- reader.run();
- var item = reader.item;
-
- //check if the item is an error
- if (item instanceof Ci.ffIErrorItem) {
- this._error.init(item.severity, name, item.message);
- return false;
- }
-
- //copy the file to the icon directory
- var file = this._dskSvc.get(aFile.leafName, TYPE_ICONS);
- file.createUnique(file.NORMAL_FILE_TYPE, PERMS_FILE);
- try {
- this._dskSvc.copy(aFile, file);
- } catch(e) {
- this._error.init(SEVERITY_ERROR, name, e.message);
- return false;
- }
-
- //remove the item if it is currently installed
- var success = true;
- if (this.hasItem(item.ID))
- success = this.deleteItem(item.ID);
-
- //check if delete was successful
- if (!success) {
- try {
- removeFile(file);
- } catch(e) {}
- var err = this.lastError;
- this._error.init(err.severity, name, err.message);
- return false;
- }
-
- //set the jar property
- item.setProperty("jar", file.leafName);
-
- //save the item
- this._items[item.ID] = item;
-
- //flush async
- this._flushData();
-
- //notify observers
- this._obSvc.notifyObservers(this, "forecastfox-icons", "setItem");
-
- //return successful
- return true;
- },
-
- /**
- * Remove a pack item. It also removes that pack file.
- * Use the lastError property for more information.
- *
- * @param ID of the pack item.
- * @return False if pack could not be deleted.
- */
- deleteItem: function PackService_deleteItem(aID)
- {
- //do nothing if we don't have item
- if (!this.hasItem(aID))
- return false;
-
- //if the item is the current then load the next one
- if (!this.isBatch && this.current.ID == aID)
- this.current = this._nextItem();
-
- //remove the items file
- this._removeFiles(this._items[aID].getProperty("jar"));
-
- //remove the item
- delete this._items[aID];
-
- //flush async
- this._flushData();
-
- //notify observers
- this._obSvc.notifyObservers(this, "forecastfox-icons", "deleteItem");
-
- //return successful
- return true;
- },
-
- /**
- * Turn on batch mode. Observers will get a notification of this.
- * They will still get notified for every individual change, but they are
- * free to ignore those notifications.
- * Use this when a lot of changes are about to happen, and it would be
- * useless to refresh the display (or the backend store) for every change.
- * Caller must make sure to also call endBatch. Make sure all errors
- * are caught!
- */
- startBatch: function PackService_startBatch()
- {
- //do nothing if already batch
- if (this.isBatch)
- return;
-
- //mark batch
- this._isBatch = true;
-
- //notify observers
- this._obSvc.notifyObservers(this, "forecastfox-icons", "startBatch");
- },
-
- /**
- * Turn off batch mode.
- */
- endBatch: function PackService_endBatch()
- {
- //do nothing if not batch
- if (!this.isBatch)
- return;
-
- //make sure we have the default profile
- if (!this.hasItem("default"))
- var item = this._getDefaultItem();
-
- //make sure we have a current profile
- if (!this.hasItem(getPref("icons.current")))
- this.current = item;
-
- //mark not batch
- this._isBatch = false;
-
- // flush data if we have pending changes
- if (this._flushPending) {
- this._flushData();
- this._flushPending = false;
- }
-
- //notify observers
- this._obSvc.notifyObservers(this, "forecastfox-icons", "endBatch");
- },
-
- ////////////////////////////////
- // Internal Functions
-
- /**
- * Select the next pack item.
- */
- _nextItem: function PackService__nextItem()
- {
- //setup variables
- var ids = [];
- var index = 0;
- var current = this.current.ID;
- var found = false;
-
- //loop through items
- for (var id in this._items) {
-
- //mark that we found the current
- if (current == id)
- found = true;
-
- //increment the index
- if (!found)
- index++;
-
- //save the id
- ids.push(id);
- }
-
- //return the next item
- index = (index + 1 < ids.length) ? index + 1 : 0;
- return this._items[ids[index]];
- },
-
- /**
- * Load an item into preferences.
- *
- * @param The item to load.
- */
- _loadItem: function PackService__loadItem(aItem)
- {
- //mark we are loading
- this._isLoading = true;
-
- //set the current pref
- setPref("icons.current", aItem.ID);
-
- //mark we are finished loading
- this._isLoading = false;
- },
-
- /**
- * Ensure there is an item available for the current property.
- *
- * @return A profile item.
- */
- _ensureItem: function PackService__ensureItem()
- {
- //get the current item
- var item = this.getItem(getPref("icons.current"));
- if (!item) {
-
- //get all items
- var items = this.getItems({});
-
- //set to the first one
- if (items.length > 0)
- item = items[0];
-
- //get the default
- else
- item = this._getDefaultItem();
- }
-
- //return the item
- return item;
- },
-
- /**
- * Get the default icon pack item.
- *
- * @return A ffIPackItem.
- */
- _getDefaultItem: function PackService__getDefaultItem()
- {
- //log that we are installing the default
- this._dskSvc.log("Installing the default icon pack.", null, null);
-
- //get the default.jar file
- var file = this._dskSvc.get("default.jar", TYPE_DEFAULTS);
-
- //install the item
- var success = this.setItem(file);
-
- //install was unsuccessful
- var item;
- if (!success) {
- this._dskSvc.log("Failed to install the default pack because: " +
- this.lastError.toString(), null, null);
- item = Cc["@ensolis.com/forecastfox/pack-item;1"].
- createInstance(Ci.ffIPackItem);
- this._items["default"] = item;
- this._flushData();
-
- //install was successful
- } else
- item = this.getItem("default");
-
- //return the item
- return item;
- },
-
- /**
- * Try to remove old icon pack files that are marked for deletion.
- *
- * @param A file to try removing
- */
- _removeFiles: function PackService__removeFiles(aName)
- {
- //get the names stored in prefs
- var names = getPref("icons.uninstallfiles");
- if (!aName && names == "")
- return;
-
- //split the names into an array and add the passed in name
- if (names != "")
- names = names.split(";");
- else
- names = [];
- if (aName)
- names.push(aName);
-
- //loop through the file names
- var dir = this._dskSvc.get("", TYPE_ICONS);
- var remaining = [];
- for (var i=0; i<names.length; i++) {
- var file = dir.clone();
- file.append(names[i]);
-
- //skip if file does not exist
- if (!file.exists())
- continue;
-
- //try to remove the file
- try {
- removeFile(file);
-
- //save the name since we could not remove it
- } catch (e) {
- remaining.push(file.leafName);
- }
- }
-
- //save the remaining files back to prefs
- setPref("icons.uninstallfiles", remaining.join(";"));
- },
-
- /**
- * Create a pack item from a DOM node.
- *
- * @param The pack DOM node.
- * @return A pack item.
- */
- _createItem: function PackService__createItem(aNode)
- {
- //create an empty pack item
- var item = Cc["@ensolis.com/forecastfox/pack-item;1"].
- createInstance(Ci.ffIPackItem);
-
- //set the name and ID
- item.setProperty("name", aNode.getAttribute("name"));
- item.setProperty("ID", aNode.getAttribute("id"));
-
- //loop through property nodes
- var properties = aNode.getElementsByTagName("properties")[0];
- properties = properties.getElementsByTagName("property");
- for (var i=0; i<properties.length; i++) {
- var property = properties[i];
-
- //get the property node attributes
- var name = property.getAttribute("name");
- var value = property.getAttribute("value");
- var type = property.getAttribute("type");
-
- //set the item property based on type
- switch (type) {
- case "Int":
- item.setProperty(name, Number(value));
- break;
- case "Bool":
- item.setProperty(name, Boolean(value));
- break;
- case "Char":
- default:
- item.setProperty(name, value);
- break;
- }
- }
-
- //loop through the exemption nodes
- var exemptions = aNode.getElementsByTagName("exemptions")[0];
- exemptions = exemptions.getElementsByTagName("exemption");
- for (i=0; i<exemptions.length; i++) {
-
- //create an empty icon item
- var icon = Cc["@ensolis.com/forecastfox/icon-item;1"].
- createInstance(Ci.ffIIconItem);
-
- //loop through property nodes
- properties = exemptions[i].getElementsByTagName("property");
- for (var j=0; j<properties.length; j++) {
- property = properties[j];
-
- //get the property node attributes
- name = property.getAttribute("name");
- value = property.getAttribute("value");
- type = property.getAttribute("type");
-
- //set the icon property based on type
- switch (type) {
- case "Int":
- icon.setProperty(name, Number(value));
- break;
- case "Bool":
- icon.setProperty(name, Boolean(value));
- break;
- case "Char":
- default:
- icon.setProperty(name, value);
- break;
- }
- }
-
- //add the icon to the pack
- icon.setProperty("isExemption", true);
- item.setItem(icon);
- }
-
- //return the item
- return item;
- },
-
-
- /**
- * Create a DOM node from a pack item.
- *
- * @param The pack item.
- * @param The owner document of the node.
- * @return The DOM node.
- */
- _createNode: function PackService__createNode(aItem, aDoc)
- {
- //create pack, properties, and exemptions nodes
- var pack = aDoc.createElementNS(ICONS_NS, "pack");
- var properties = aDoc.createElementNS(ICONS_NS, "properties");
- var exemptions = aDoc.createElementNS(ICONS_NS, "exemptions");
-
- //set the name and id
- pack.setAttribute("id", aItem.ID);
- pack.setAttribute("name", aItem.name);
-
- //loop through the items properties
- var props = aItem.properties;
- while (props.hasMore()) {
- var name = props.getNext();
-
- //skip ID and name properties
- if (name == "ID" || name == "name")
- continue;
-
- //set the node properties
- var node = aDoc.createElementNS(ICONS_NS, "property");
- var value = aItem.getProperty(name);
- node.setAttribute("name", name);
- node.setAttribute("value", String(value));
- if (typeof value == "number")
- node.setAttribute("type", "Int");
- else if (typeof value == "boolean")
- node.setAttribute("type", "Bool");
- else
- node.setAttribute("type", "Char");
-
- //append it to the properties node
- properties.appendChild(node);
- }
-
- //loop through the packs icon items
- var items = aItem.getItems(true, {});
- for (var i=0; i<items.length; i++) {
- var item = items[i];
-
- //loop through the items properties
- var exemption = aDoc.createElementNS(ICONS_NS, "exemption");
- props = item.properties;
- while (props.hasMore()) {
- name = props.getNext();
-
- //skip URL and isExemption
- if (name == "URL" || name == "isExemption")
- continue;
-
- //set the node properties
- node = aDoc.createElementNS(ICONS_NS, "property");
- value = item.getProperty(name);
- node.setAttribute("name", name);
- node.setAttribute("value", String(value));
- if (typeof value == "number")
- node.setAttribute("type", "Int");
- else if (typeof value == "boolean")
- node.setAttribute("type", "Bool");
- else
- node.setAttribute("type", "Char");
-
- //append it to the exemption node
- exemption.appendChild(node);
- }
-
- //append it to the exemptions node
- exemptions.appendChild(exemption);
- }
-
- //append properties and exemptions
- pack.appendChild(properties);
- pack.appendChild(exemptions);
-
- //return the node
- return pack;
- },
-
- /**
- * Flush changes to disk.
- *
- * @param Call file writer in blocking mode.
- */
- _flushData: function PackService__flushData()
- {
- //do nothing if in batch mode
- if (this.isBatch) {
- this._flushPending = true;
- return;
- }
-
- //do nothing if not writable
- var file = this._dskSvc.get("icons.xml", TYPE_PROFILE);
- if ((!file.exists() && !file.parent.isWritable()) ||
- (file.exists() && !file.isWritable())) {
- this._dskSvc.log("Icon pack file is not writable: " + file.path,
- null, null);
- return;
- }
-
- //create a new icons document
- var doc = this._dskSvc.create("icons", ICONS_DTD, ICONS_NS);
-
- //loop through items
- for (var id in this._items) {
- var item = this._items[id];
-
- //create the node
- var node = this._createNode(item, doc);
-
- //append it to the document
- doc.documentElement.appendChild(node);
- }
-
- //write to disk
- this._dskSvc.write(file, doc, false, false);
- },
-
- /**
- * Load the icon packs datasource.
- *
- * @return False if we could not get the packs loaded.
- */
- _loadPacks: function PackService__loadPacks()
- {
- //setup error variables
- const PREFIX = "ff.packs.load.";
- var name = this.bundle.GetStringFromName(PREFIX + "name");
- var message = "";
-
- //get icons.xml
- var dir = this._dskSvc.get("", TYPE_ICONS);
- var file = this._dskSvc.get("icons.xml", TYPE_PROFILE);
- if (file.exists()) {
-
- //file not readable-writable
- if (!file.isReadable() || !file.isWritable()) {
- message = this.bundle.formatStringFromName(PREFIX + ".perms.message",
- [file.path], 1);
- this._error.init(SEVERITY_ERROR, name, message);
- return false;
- }
-
- //read the file into a document
- var doc = this._dskSvc.read(file);
-
- //doc not valid
- if (!this._dskSvc.validate(doc, "icons")) {
- message = this.bundle.GetStringFromName(PREFIX + ".valid.message");
- this._error.init(SEVERITY_ERROR, name, message);
- return false;
- }
-
- //loop through the pack nodes
- var isDirty = false;
- var nodes = doc.getElementsByTagName("pack");
- for (var i=0; i<nodes.length; i++) {
-
- //create an item
- var item = this._createItem(nodes[i]);
-
- //make sure the jar file exists
- if (!item.hasProperty("jar")) {
- isDirty = true;
- continue;
- } else {
- file = dir.clone();
- file.append(item.getProperty("jar"));
- if (!file.exists()) {
- isDirty = true;
- continue;
- }
- }
-
- //save the item
- this._items[item.ID] = item;
- }
-
- // flush the data if it changed
- if (isDirty)
- this._flushData();
-
- //icons.xml does not exist
- } else {
-
- //log that datasource was missing
- this._dskSvc.log("Expected icons.xml, but was missing.", null, null);
-
-
- //file not readable-writable
- if (!file.parent.isReadable() || !file.parent.isWritable()) {
- message = this.bundle.formatStringFromName(PREFIX + ".perms.message",
- [file.path], 1);
- this._error.init(SEVERITY_ERROR, name, message);
- return false;
- }
-
- //loop through files in the directory
- var files = dir.directoryEntries;
- var todo = [];
- while (files.hasMoreElements()) {
-
- //save the file name to an array
- file = files.getNext().QueryInterface(Ci.nsIFile);
- if (file.leafName.match(".jar"))
- todo.push(file.leafName);
- else
- this._removeFiles(file.leafName);
- }
-
- // loop backward through the array
- while(todo.length) {
-
- //install the file
- file = this._dskSvc.get(todo.pop(), TYPE_ICONS);
- var success = this.setItem(file);
- if (!success)
- this._dskSvc.log("Failed to install icon pack because: " +
- this.lastError.toString(), null, null);
-
- //remove the old file
- this._removeFiles(file.leafName);
- }
- }
-
- //ensure we have the default icon pack
- if (!this.hasItem("default"))
- this.current = this._getDefaultItem();
-
- //load is successful
- return true;
- }
- };